package models

import (
	"cgs-server/helper"
	"cgs-server/pkg/set"
	"cgs-server/server/cgs/app/models/filter"
)

var (
	// ContainerSet 栅格，表格，标签页，卡片，子表，数据表格
	ContainerSet = set.NewSet("grid", "table", "tab", "card", "sub-form", "data-table")
)

type VForm struct {
	// WidgetList 组件列表
	WidgetList WidgetList `json:"widgetList"`

	// FormConfig 表单配置信息
	FormConfig FormConfig `json:"formConfig" bson:"formConfig"`
}

// FormConfig 表单配置信息
type FormConfig struct {
	ModelName        string      `json:"modelName"`
	RefName          string      `json:"refName"`
	RulesName        string      `json:"rulesName"`
	LabelWidth       int         `json:"labelWidth"`
	LabelPosition    string      `json:"labelPosition"`
	Size             string      `json:"size"`
	LabelAlign       string      `json:"labelAlign"`
	CssCode          string      `json:"cssCode"`
	CustomClass      interface{} `json:"customClass"`
	Functions        string      `json:"functions"`
	LayoutType       string      `json:"layoutType"`
	OnFormCreated    string      `json:"onFormCreated"`
	OnFormMounted    string      `json:"onFormMounted"`
	OnFormDataChange string      `json:"onFormDataChange"`
	OnFormValidate   string      `json:"onFormValidate"`
}

type WidgetList []Widget
type Widget map[string]interface{}

func (w Widget) Type() string {
	if w["type"] == nil {
		return ""
	}
	if s, ok := w["type"].(string); ok {
		return s
	}
	return ""
}

func (w Widget) Id() string {
	if w["id"] == nil {
		return ""
	}
	if name, ok := w["id"]; ok {
		return name.(string)
	}
	return ""
}

func (w Widget) Name() string {
	name := w.Options().Value("name")
	if name == nil {
		return ""
	}
	return name.(string)
}

func (w Widget) Label() string {
	return w.Options().Label()
}

func (w Widget) Options() VFormFieldOptions {
	if op, ok := w["options"]; ok {
		return op.(map[string]interface{})
	}
	return VFormFieldOptions{}
}

func (w Widget) IsContainer() bool {
	return ContainerSet.Contains(w.Type())
}

func (w Widget) IsFormItem() bool {
	if formItemFlag, ok := w["formItemFlag"]; ok {
		return formItemFlag.(bool)
	}
	return false
}

func (w Widget) ResolveFields(fieldList *Fields) error {
	var err error
	if w.IsContainer() {
		err = w.ResolveContainer(fieldList)
	} else if w.IsFormItem() {
		err = w.ResolveFormItem(fieldList)
	}
	return err
}

func (w Widget) ResolveContainer(fieldList *Fields) error {
	var err error
	switch w.Type() {
	case "grid":
		err = w.ResolveGrid(fieldList)
	case "table":
		err = w.ResolveTable(fieldList)
	case "tab":
		err = w.ResolveTab(fieldList)
	case "card":
		err = w.ResolveCard(fieldList)
	case "sub-form":
		err = w.ResolveSubForm(fieldList)
	}
	return err
}

func (w Widget) ResolveGrid(fieldList *Fields) error {
	var grid Grid
	err := helper.TransformType(w, &grid)
	if err != nil {
		return err
	}
	for _, col := range grid.Cols {
		err = col.WidgetList.ResolveFields(fieldList)
		if err != nil {
			return err
		}
	}
	return nil
}
func (w Widget) ResolveTable(fieldList *Fields) error {
	var table Table
	err := helper.TransformType(w, &table)
	if err != nil {
		return err
	}
	for _, row := range table.Rows {
		for _, col := range row.Cols {
			err = col.WidgetList.ResolveFields(fieldList)
			if err != nil {
				return err
			}
		}
	}
	return nil
}
func (w Widget) ResolveTab(fieldList *Fields) error {
	var tab Tab
	err := helper.TransformType(w, &tab)
	if err != nil {
		return err
	}
	for _, pane := range tab.Tabs {
		err = pane.WidgetList.ResolveFields(fieldList)
		if err != nil {
			return err
		}
	}
	return nil
}
func (w Widget) ResolveCard(fieldList *Fields) error {
	var card Card
	err := helper.TransformType(w, &card)
	if err != nil {
		return err
	}
	err = card.WidgetList.ResolveFields(fieldList)
	if err != nil {
		return err
	}
	return nil
}
func (w Widget) ResolveSubForm(fieldList *Fields) error {
	var subForm SubForm
	err := helper.TransformType(w, &subForm)
	if err != nil {
		return err
	}
	subFields := Fields{}
	err = subForm.WidgetList.ResolveFields(&subFields)
	field := Field{
		Name:      w.Name(),
		Alia:      w.Label(),
		DataType:  filter.GetDataType(w.Type()),
		Options:   w.Options(),
		SubFields: &subFields,
	}
	*fieldList = append(*fieldList, &field)
	if err != nil {
		return err
	}
	return nil
}

func (w Widget) ResolveFormItem(fieldList *Fields) error {
	field := Field{
		Name:     w.Name(),
		Alia:     w.Label(),
		DataType: filter.GetDataType(w.Type()),
		Options:  w.Options(),
	}
	*fieldList = append(*fieldList, &field)
	return nil
}

// ResolveFields 从配置数据中解析出所有的字段信息
func (vf *VForm) ResolveFields() (fieldList Fields, err error) {
	err = vf.WidgetList.ResolveFields(&fieldList)
	return
}

func (wgList WidgetList) ResolveFields(fieldList *Fields) error {
	var err error
	for _, widget := range wgList {
		err = widget.ResolveFields(fieldList)
		if err != nil {
			return err
		}
	}

	return nil
}

type WidgetBaseField struct {
	Id           string `json:"id"`
	Type         string `json:"type"`
	Icon         string `json:"icon"`
	Category     string `json:"category,omitempty"`
	FormItemFlag bool   `json:"formItemFlag,omitempty"`
}

type WidgetBaseOptions struct {
	Name        string      `json:"name"`
	Hidden      bool        `json:"hidden,omitempty"`
	CustomClass interface{} `json:"customClass"`
}

// 容器

// Grid 栅格
type Grid struct {
	WidgetBaseField `json:",inline"`

	Cols    []GridCol   `json:"cols"`
	Options GridOptions `json:"options"`
}

// GridCol 栅格列
type GridCol struct {
	WidgetBaseField `json:",inline"`

	Internal   bool           `json:"internal"`
	WidgetList WidgetList     `json:"widgetList"`
	Options    GridColOptions `json:"options"`
}

type GridColOptions struct {
	WidgetBaseOptions `json:",inline"`

	Span       *int `json:"span"`
	Offset     *int `json:"offset"`
	Push       *int `json:"push"`
	Pull       *int `json:"pull"`
	Responsive bool `json:"responsive"`
	Md         *int `json:"md"`
	Sm         *int `json:"sm"`
	Xs         *int `json:"xs"`
}

type GridOptions struct {
	WidgetBaseOptions `json:",inline"`

	Gutter    *int `json:"gutter"`
	ColHeight *int `json:"colHeight"`
}

// Table 表格
type Table struct {
	WidgetBaseField `json:",inline"`

	Rows    []TableCols  `json:"rows"`
	Options TableOptions `json:"options"`
}

type TableOptions struct {
	WidgetBaseOptions `json:",inline"`
}

type TableCols struct {
	Id     string      `json:"id"`
	Merged bool        `json:"merged"`
	Cols   []TableCell `json:"cols"`
}

type TableCell struct {
	WidgetBaseField `json:",inline"`

	Internal   bool             `json:"internal"`
	WidgetList WidgetList       `json:"widgetList"`
	Merged     bool             `json:"merged"`
	Options    TableCellOptions `json:"options"`
}

type TableCellOptions struct {
	WidgetBaseOptions `json:",inline"`

	CellWidth  string `json:"cellWidth"`
	CellHeight string `json:"cellHeight"`
	Colspan    *int   `json:"colspan"`
	Rowspan    *int   `json:"rowspan"`
}

// Tab 标签页
type Tab struct {
	WidgetBaseField `json:",inline"`

	DisplayType string     `json:"displayType"`
	Tabs        []TabPane  `json:"tabs"`
	Options     TabOptions `json:"options"`
}

type TabOptions struct {
	WidgetBaseOptions `json:",inline"`
}

type TabPane struct {
	WidgetBaseField `json:",inline"`

	Internal   bool           `json:"internal"`
	WidgetList WidgetList     `json:"widgetList"`
	Options    TabPaneOptions `json:"options"`
}

type TabPaneOptions struct {
	WidgetBaseOptions `json:",inline"`

	Label    string `json:"label"`
	Active   bool   `json:"active"`
	Disabled bool   `json:"disabled"`
}

// Card 卡片
type Card struct {
	WidgetBaseField `json:",inline"`

	WidgetList WidgetList  `json:"widgetList"`
	Options    CardOptions `json:"options"`
}

type CardOptions struct {
	WidgetBaseOptions `json:",inline"`

	Label     string `json:"label"`
	Folded    bool   `json:"folded"`
	ShowFold  bool   `json:"showFold"`
	CardWidth string `json:"cardWidth"`
	Shadow    string `json:"shadow"`
}

// SubForm 子表字段
type SubForm struct {
	WidgetBaseField `json:",inline"`

	WidgetList WidgetList     `json:"widgetList"`
	Options    SubFormOptions `json:"options"`
}

type SubFormOptions struct {
	WidgetBaseOptions `json:",inline"`

	ShowBlankRow       bool   `json:"showBlankRow"`
	ShowRowNumber      bool   `json:"showRowNumber"`
	LabelAlign         string `json:"labelAlign"`
	OnSubFormRowAdd    string `json:"onSubFormRowAdd"`
	OnSubFormRowInsert string `json:"onSubFormRowInsert"`
	OnSubFormRowDelete string `json:"onSubFormRowDelete"`
	OnSubFormRowChange string `json:"onSubFormRowChange"`
}

// 基础字段

type VFormFieldOptions map[string]interface{}

func (vffo VFormFieldOptions) Value(key string) interface{} {
	if s, ok := vffo[key]; ok {
		return s
	}
	return nil
}

func (vffo VFormFieldOptions) Label() string {
	value := vffo.Value("label")
	if value != nil {
		return value.(string)
	}
	return ""
}

// Input 单行输入
type Input struct {
	WidgetBaseField `json:",inline"`

	Options VFormFieldOptions `json:"options"`
}

type InputOptions struct {
	WidgetBaseOptions `json:",inline"`

	Label                string `json:"label"`
	LabelAlign           string `json:"labelAlign"`
	Type                 string `json:"type"`
	DefaultValue         string `json:"defaultValue"`
	PlaceHolder          string `json:"placeHolder"`
	ColumnWidth          string `json:"columnWidth"`
	Size                 string `json:"size"`
	LabelWidth           string `json:"labelWidth"`
	LabelHidden          bool   `json:"labelHidden"`
	ReadOnly             bool   `json:"readOnly"`
	Disabled             bool   `json:"disabled"`
	Clearable            bool   `json:"clearable"`
	ShowPassword         bool   `json:"showPassword"`
	Required             bool   `json:"required"`
	Validation           string `json:"validation"`
	ValidationHint       string `json:"validationHint"`
	LabelIconClass       string `json:"labelIconClass"`
	LabelIconPosition    string `json:"labelIconPosition"`
	LabelTooltip         string `json:"labelTooltip"`
	MinLength            string `json:"minLength"`
	MaxLength            string `json:"maxLength"`
	ShowWordLimit        bool   `json:"showWordLimit"`
	PrefixIcon           string `json:"prefixIcon"`
	SuffixIcon           string `json:"suffixIcon"`
	AppendButton         bool   `json:"appendButton"`
	AppendButtonDisabled bool   `json:"appendButtonDisabled"`
	ButtonIcon           string `json:"buttonIcon"`
	OnCreated            string `json:"onCreated"`
	OnMounted            string `json:"onMonted"`
	OnInput              string `json:"onInput"`
	OnChange             string `json:"onChange"`
	OnFocus              string `json:"onFocus"`
	OnBlur               string `json:"onBlur"`
	OnValidate           string `json:"onValidate"`
}

// Textarea 多行输入
type Textarea struct {
	WidgetBaseField `json:",inline"`

	Options VFormFieldOptions `json:"options"`
}

type TextareaOptions struct {
	WidgetBaseOptions `json:",inline"`
}

// Number 计数器
type Number struct {
	WidgetBaseField `json:",inline"`

	Options VFormFieldOptions `json:"options"`
}
